package org.vison.wonfu.framework.soa;

import org.vison.wonfu.framework.soa.exception.RpcException;

import java.io.Serializable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;

public interface Result extends Serializable {
    /**
     * Returns {@code true} if completed in any fashion: normally,
     * exceptionally, or via cancellation.
     */
    boolean isDone();

    /**
     * ！！！调用后会等待同步执行结束，不熟悉异步逻辑的同学请谨慎调用<br/>
     *
     * Waits if necessary for the computation to complete, and then
     * retrieves its response.
     */
    Response get() throws RpcException;

    /**
     * ！！！调用后会等待同步执行结束，不熟悉异步逻辑的同学请谨慎调用<br/>
     *
     * Waits if necessary for at most the given time for the computation
     * to complete, and then retrieves its response, if available.
     */
    Response get(long timeout, TimeUnit unit) throws RpcException;

    /**
     * Set invoke response value
     */
    void setValue(Object value);

    /**
     * Set invoke response exception
     */
    void setException(Throwable t);

    /**
     * Recreate
     * <ul>
     *     <li>{@link Response#recreate()} for SYNC mode</li>
     *     <li>{@link FutureAdapter#toFuture(CompletableFuture)} for FUTURE mode</li>
     * </ul>
     *
     * @see Response#recreate()
     * @see FutureAdapter#toFuture(CompletableFuture)
     */
    Object recreate() throws Throwable;

    /**
     * Get Result internal CompletableFuture
     */
    CompletableFuture<Response> getFuture();

    /**
     * Replace Result internal CompletableFuture
     */
    void setFuture(CompletableFuture<Response> future);

    /**
     * Add a callback which can be triggered when the RPC call finishes.
     * <p>
     * This method will guarantee the callback being triggered under the same context as when the call was started
     *
     * @see CompletableFuture#whenComplete(BiConsumer)
     */
    Result whenComplete(BiConsumer<Response, Throwable> fn);

    /**
     * Add a handle which can be triggered when the RPC call finishes.
     * <p>
     * This method will guarantee the callback being triggered under the same context as when the call was started
     *
     * @see CompletableFuture#handle(BiFunction)
     */
    Result handle(BiFunction<Response, Throwable, ? extends Response> fn);
}
